/*
在计算机界中，我们总是追求用有限的资源获取最大的收益。

现在，假设你分别支配着 m 个 0 和 n 个 1。另外，还有一个仅包含 0 和 1 字符串的数组。

你的任务是使用给定的 m 个 0 和 n 个 1 ，找到能拼出存在于数组中的字符串的最大数量。每个 0 和 1 至多被使用一次。

注意:

给定 0 和 1 的数量都不会超过 100。
给定字符串数组的长度不会超过 600。
示例 1:

输入: Array = {"10", "0001", "111001", "1", "0"}, m = 5, n = 3
输出: 4

解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出，即 "10","0001","1","0" 。
示例 2:

输入: Array = {"10", "0", "1"}, m = 1, n = 1
输出: 2

解释: 你可以拼出 "10"，但之后就没有剩余数字了。更好的选择是拼出 "0" 和 "1" 。

*/


class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) {
        
        int len=nums.size();
        int sum=accumulate(nums.begin(),nums.end(),0);
        if(S>sum||(S+sum)%2==1){
            return 0;
        }
        //dp[i][j]前i个数中部分和为j的组合数
        int target=(S+sum)/2;
        /*
        vector<vector<int>> dp(len,vector<int>(target+1,0));

        dp[0][0]=(nums[0]==0?2:1);
        for(int j=1;j<=target;j++){
            if(nums[0]==j){
                dp[0][j]=1;
                break;
            }
        }
        for(int i=1;i<len;i++){
            for(int j=0;j<=target;j++){
                dp[i][j]=dp[i-1][j]+(j-nums[i]>=0?dp[i-1][j-nums[i]]:0);
            }
        }
        return dp[len-1][target];
        */
        vector<int> dp(target+1,0);
        dp[0]=1;
        for(int i=0;i<len;i++){
            for(int j=target;j>=0;j--){
                dp[j]=dp[j]+(j-nums[i]>=0?dp[j-nums[i]]:0);
            }
        }
        return dp[target];
    }
};

/*
        cout<<"j:   ";
        for(int j=0;j<=target;j++){
            cout<<" "<<j;
        }
        cout<<endl;
        for(int i=0;i<len;i++){
            cout<<"i: "<<i;
            for(int j=0;j<=target;j++){
                cout<<" "<<dp[i][j];
            }
            cout<<endl;
        }
*/